home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UTIL / MEMORY / OLD / MEM208SRC / !Memphis / c / Lfile < prev    next >
Text File  |  1993-09-09  |  9KB  |  369 lines

  1. /*
  2.  * Lfile.c
  3.  * Part of the !Memphis distribution
  4.  * (c) bdb/nas, 1991-3
  5.  */
  6.  
  7. /* #define DEBUG */
  8.  
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include "kernel.h"
  13. #include "swis.h"
  14. #include "_swis.h"
  15. #include "util.h"
  16. #include "compress.h"
  17.  
  18. /* debug support */
  19. #ifdef DEBUG
  20. #define DEBUGF printf
  21. #else
  22. #define DEBUGF 1?(void)0:(void)printf
  23. #endif
  24.  
  25. static int ftruncate(int fp,int len)
  26. { return _kernel_osargs(3,fp,len)==_kernel_ERROR?EOF:0;
  27. }
  28.  
  29. static int read(int fd, void *buff, int nbytes)
  30. { if (_swix(OS_GBPB,_INR(0,3)|_OUT(3),4,fd,buff,nbytes,&fd))
  31.     return EOF;
  32.   return nbytes-fd;
  33. }
  34.  
  35. static int write(int fd, void *buff, int nbytes)
  36. { if (_swix(OS_GBPB,_INR(0,3)|_OUT(3),2,fd,buff,nbytes,&fd))
  37.     return EOF;
  38.   return nbytes-fd;
  39. }
  40.  
  41. static int readat(int fd, int offset, void *buff, int nbytes)
  42. { if (_swix(OS_GBPB,_INR(0,4)|_OUT(3),3,fd,buff,nbytes,offset,&fd))
  43.     return EOF;
  44.   return nbytes-fd;
  45. }
  46.  
  47. static int writeat(int fd, int offset, void *buff, int nbytes)
  48. { if (_swix(OS_GBPB,_INR(0,4)|_OUT(3),1,fd,buff,nbytes,offset,&fd))
  49.     return EOF;
  50.   return nbytes-fd;
  51. }
  52.  
  53. #define OREAD 0
  54. #define OCREATE 1
  55. #define OREADWRITE 2
  56.  
  57. static int open(char *name,int mode)
  58. { if (mode<0 || mode>2) 
  59.     return EOF;
  60.   if (_swix(OS_Find,_IN(0)|_IN(1)|_OUT(0),0x4f+mode*0x40,
  61.         name,&mode))
  62.     return EOF;
  63.   return mode;
  64. }
  65.  
  66. static int close(int fd)
  67. { if (_swix(OS_Find,_IN(0)|_IN(1),0,fd))
  68.     return EOF;
  69.   return 0;
  70. }
  71.  
  72. #define L_SET 0
  73. #define L_INCR 1
  74. #define L_XTND 2
  75.  
  76. static int lseek(int fd,int offset,int whence)
  77. { switch (whence)
  78.   { case L_SET:
  79.       break;
  80.     case L_INCR:
  81.       whence = _kernel_osargs(0,fd,0);
  82.       if (whence==_kernel_ERROR) return EOF;
  83.       offset += whence;
  84.       break;
  85.     case L_XTND:
  86.       whence = _kernel_osargs(2,fd,0);
  87.       if (whence==_kernel_ERROR) return EOF;
  88.       offset += whence;
  89.       break;
  90.     default:
  91.       return EOF;
  92.   }
  93.   return _kernel_osargs(1,fd,offset)==_kernel_ERROR?EOF:offset;
  94. }
  95.  
  96. static DEFERR(mb_memory,0,"Out of memory");
  97. static DEFERR(mb_NotFound,0,"Lump file not found");
  98. static DEFERR(mb_Read,0,"Lump file read failed");
  99. static DEFERR(mb_Create,0,"Could not create Lump file");
  100. static DEFERR(mb_Write,0,"Lump file write failed");
  101.  
  102. #include "Lfile.h"
  103. #define PAGESIZE 32768  /* Lumps we compress data in */
  104.  
  105. struct extent { int offset, len; };     /* a len of 0 means this extent isn't used */
  106.  
  107. struct lhandle
  108. { int size;             /* Uncompressed size of the file */
  109.   int numpages;         /* amount of memory currently allocated */
  110.   struct extent *pages; /* where in file corresponds to each page */
  111.   int changed:1;        /* Whether changed since opened */
  112.   int fp;               /* os file handle */
  113. };
  114.  
  115. /* The format of a Lfile is as follows
  116.  * Each 32K page of data is compressed separately, and stored as an extent in the file
  117.  * When the file is closed, the index of these is stored at the end of the file, followed
  118.  * by its uncompressed length (which tells how many extents there are
  119.  */
  120.  
  121. static char *pagebuf;
  122. static char *compressbuf;
  123. static int pbpage;
  124. static LHANDLE pbhandle;
  125. static int pbchanged;
  126.  
  127. static _kernel_oserror *putpage(LHANDLE h,int page)
  128. { int i;
  129.   struct extent e;
  130.   DEBUGF("putpage: %p %d...",h,page);
  131.   DEBUGF("size %d\n", h->size);
  132.   if (h->size < PAGESIZE)
  133.     e.len = compress(pagebuf,h->size,compressbuf,PAGESIZE);
  134.   else
  135.     e.len = compress(pagebuf,PAGESIZE,compressbuf,PAGESIZE);
  136.   DEBUGF("compress to %d,",e.len);
  137.   h->changed = 1;
  138.   e.offset = 0;
  139. lp:
  140.   for (i=0;i<h->numpages;i++)
  141.     if (i!=page && ( e.offset>=h->pages[i].offset ? e.offset < h->pages[i].offset+h->pages[i].len :
  142.                                                     h->pages[i].offset < e.offset+e.len ))
  143.     { e.offset = h->pages[i].offset+h->pages[i].len;
  144.       goto lp;
  145.     }
  146.   h->pages[page] = e;
  147.   DEBUGF("offset=%x,",e.offset);
  148.   if (writeat(h->fp,e.offset,compressbuf,e.len)!=e.len)
  149.     return ERR(mb_Write);
  150.   pbchanged = 0;
  151.   DEBUGF("ok\n");
  152.   return NULL;
  153. }
  154.  
  155. static _kernel_oserror *getpage(LHANDLE h,int page)
  156. { _kernel_oserror *err;
  157.   struct extent e;
  158.   DEBUGF("getpage: %p %d...",h,page);
  159.   if (pbhandle==h && pbpage==page)
  160.   { DEBUGF("bufferd ok\n");
  161.     return NULL;
  162.   }
  163.   if (pbhandle && pbchanged)
  164.   { err = putpage(pbhandle,pbpage);
  165.     if (err) return err;
  166.   }
  167.   e = h->pages[page];
  168.   if (e.len)
  169.   { if (readat(h->fp,e.offset,compressbuf,e.len)!=e.len)
  170.       return ERR(mb_Read);
  171.     DEBUGF("read offset %x+%d size %d,",e.offset,e.len,h->size);
  172.     if (h->size == e.len)
  173.       uncompress(compressbuf,e.len,pagebuf,e.len);
  174.     else
  175.       uncompress(compressbuf,e.len,pagebuf,PAGESIZE);
  176.   }
  177.   else
  178.     memset(pagebuf,0,PAGESIZE);
  179.   pbhandle = h;
  180.   pbpage = page;
  181.   pbchanged = 0;
  182.   DEBUGF("ok\n");
  183.   return NULL;
  184. }
  185.  
  186. /* #undef DEBUGF
  187. #define DEBUGF 1?(void)0:(void)printf
  188.  */
  189.  
  190. _kernel_oserror *Linit(void)
  191. {
  192.   DEBUGF("Linit....");
  193.   pagebuf = malloc(PAGESIZE);
  194.   pbhandle = NULL;
  195.   compressbuf = malloc(PAGESIZE);
  196.   if (!pagebuf || !compressbuf)
  197.     return ERR(mb_memory);
  198.   DEBUGF("ok\n");
  199.   return NULL;
  200. }
  201. _kernel_oserror *Lfinish(void)
  202. {
  203.   DEBUGF("Lfinish...");
  204.   if (pbhandle && pbchanged)
  205.     putpage(pbhandle,pbpage);
  206.   free(pagebuf);
  207.   free(compressbuf);
  208.   DEBUGF("ok\n");
  209.   return NULL;
  210. }
  211. _kernel_oserror *Lcreate(char *filename,int length)
  212. { int fp;
  213.   struct extent e;
  214.   int n;
  215.   DEBUGF("Lcreate %s %d...",filename,length);
  216.   fp = open(filename,OCREATE);
  217.   if (fp==EOF)
  218.     return ERR(mb_Create);
  219.   n = (length + PAGESIZE-1)/PAGESIZE;
  220.   e.offset = e.len = 0;
  221.   for (;n--;)
  222.     if (write(fp,&e,sizeof(struct extent))==EOF)
  223.       goto erk;
  224.   if (write(fp,&length,sizeof(int))==EOF)
  225.     goto erk;
  226.   close(fp);
  227.   DEBUGF("ok\n");
  228.   return NULL;
  229. erk:
  230.   close(fp);
  231.   remove(filename);
  232.   return ERR(mb_Write);
  233. }
  234.  
  235. _kernel_oserror *Lopen(char *filename, LHANDLE *h)
  236. {
  237.   LHANDLE p=malloc(sizeof(struct lhandle));
  238.   int k;
  239.   DEBUGF("Lopen %s..",filename);
  240.   if (!p)
  241.     return ERR(mb_memory);
  242.   p->fp = open(filename,OREADWRITE);
  243.   if (p->fp==EOF)
  244.     return ERR(mb_NotFound);
  245.   k = sizeof(p->size);
  246.   if (lseek(p->fp,-k,L_XTND)==EOF ||
  247.       read(p->fp,&p->size,k)!=k)
  248.     return ERR(mb_Read);
  249.   p->numpages = (p->size + PAGESIZE-1)/PAGESIZE;
  250.   DEBUGF("size %d, pages=%d..",p->size,p->numpages);
  251.   k = sizeof(struct extent)*p->numpages;
  252.   p->pages = malloc(k);
  253.   p->changed = 0;
  254.   if (!p->pages)
  255.   {
  256.     close(p->fp);
  257.     free(p);
  258.     return ERR(mb_memory);
  259.   }
  260.   if (lseek(p->fp,-sizeof(p->size)-k,L_XTND)==EOF ||
  261.       read(p->fp,p->pages,k)!=k)
  262.     return ERR(mb_Read);
  263.   *h=p;
  264.   DEBUGF("=%p ok\n",p);
  265.   return NULL;
  266. }
  267.  
  268. _kernel_oserror *Lclose(LHANDLE h)
  269. { _kernel_oserror *err=NULL;
  270.   int i,m,k;
  271.   m = 0;
  272.   DEBUGF("Lclose %p...",h);
  273.   if (pbhandle==h && pbchanged)
  274.     putpage(h,pbpage);
  275.   if (h->changed)
  276.   {
  277.     for (i=0;i<h->numpages;i++)
  278.       if (m<h->pages[i].offset+h->pages[i].len)
  279.         m = h->pages[i].offset+h->pages[i].len;
  280.     k = sizeof(struct extent)*h->numpages;
  281.     if (writeat(h->fp,m,h->pages,k)!=k ||
  282.         write(h->fp,&h->size,sizeof(int))!=sizeof(int) ||
  283.         ftruncate(h->fp,m+k+sizeof(int))==EOF)
  284.       err = ERR(mb_Write);
  285.   }
  286.   close(h->fp);
  287.   free(h->pages);
  288.   free(h);
  289.   if (pbhandle==h)
  290.     pbhandle = NULL;
  291.   DEBUGF("ok\n");
  292.   return err;
  293. }
  294.  
  295.  
  296. _kernel_oserror *Lread(LHANDLE h,int offset,int len, char *ptr)
  297. { _kernel_oserror *err;
  298.   int page,o,l;
  299.   DEBUGF("Lread %p %x+%x %p..",h,offset,len,ptr);
  300. lp:
  301.   page = offset/PAGESIZE;
  302.   o = offset % PAGESIZE;
  303.   err = getpage(h,page);
  304.   if (err) return err;
  305.   l = PAGESIZE - o;
  306.   if (l>len) l = len;
  307.   memcpy(ptr,&pagebuf[o],l);
  308.   if (l<len)
  309.   { len -= l;
  310.     offset += l;
  311.     ptr = (char *)ptr + l;
  312.     goto lp;
  313.   }
  314.   DEBUGF("ok\n");
  315.   return NULL;
  316. }
  317.  
  318. _kernel_oserror *Lwrite(LHANDLE h,int offset,int len, char *ptr)
  319. { _kernel_oserror *err;
  320.   int page,o,l;
  321.   DEBUGF("Lwrite %p %x+%x %p..",h,offset,len,ptr);
  322. lp:
  323.   page = offset/PAGESIZE;
  324.   o = offset % PAGESIZE;
  325.   err = getpage(h,page);
  326.   if (err) return err;
  327.   l = PAGESIZE - o;
  328.   if (l>len) l = len;
  329.   memcpy(&pagebuf[o],ptr,l);
  330.   pbchanged = 1;
  331.   if (l<len)
  332.   { len -= l;
  333.     offset += l;
  334.     ptr = (char *)ptr + l;
  335.     goto lp;
  336.   }
  337.   DEBUGF("ok\n");
  338.   return NULL;
  339. }
  340.  
  341. _kernel_oserror *Lsetlength(LHANDLE h,int len)
  342. { int newnumpages = (len + PAGESIZE-1)/PAGESIZE;
  343.   int i;
  344.   struct extent *newpages;
  345.   DEBUGF("Lsetlength %p %x...",h,len);
  346.   if (pbhandle==h && pbchanged)
  347.     putpage(h,pbpage);
  348.   if (pbhandle==h)
  349.     pbhandle=NULL;
  350.   h->changed = 1;
  351.   if (h->numpages==newnumpages)
  352.   { h->size = len;
  353.     DEBUGF("pages same ok\n");
  354.     return NULL;
  355.   }
  356.   newpages = malloc(sizeof(struct extent)*newnumpages);
  357.   if (!newpages)
  358.     return ERR(mb_memory);
  359.   memcpy(newpages,h->pages,sizeof(struct extent)*newnumpages);
  360.   for (i=h->numpages;i<newnumpages;i++)
  361.     newpages[i].len = 0;
  362.   free(h->pages);
  363.   h->size = len;
  364.   h->pages = newpages;
  365.   h->numpages = newnumpages;
  366.   DEBUGF("ok\n");
  367.   return NULL;
  368. }
  369.